/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import { TypeNode, SyntaxKind, TypeReferenceNode } from 'ts-morph';
import { PropertyKind, TypeStructure, SerializerMetadata, TypeKind, EnumDetails } from '../Types';
import { CustomTypeAnalyzer } from '../analyzers/CustomTypeAnalyzer';
import { BaseTypeHandler } from './BaseTypeHandler';
import { ITypeHandler } from './ITypeHandler';
import { CustomError, ErrorCodes } from '../utils/CustomError';

class EnumHandler extends BaseTypeHandler implements ITypeHandler {
  readonly name = 'EnumHandler';
  readonly kind = PropertyKind.ENUM;
  readonly priority = 95; // 高优先级，优先于自定义类Handler

  // ==================== 阶段1: 类型识别 ====================

  matches(typeNode: TypeNode): boolean {
    // 必须是TypeReference
    if (typeNode.getKind() !== SyntaxKind.TypeReference) {
      return false;
    }

    // 查找类型定义，判断是否为枚举
    const typeRef = typeNode as TypeReferenceNode;
    const customTypeName = typeRef.getTypeName().getText();
    const typeDependency = CustomTypeAnalyzer.getInstance()
      .findDefinition(customTypeName, typeRef.getSourceFile());

    return typeDependency?.typeKind === TypeKind.ENUM;
  }

  // ==================== 阶段2: 类型解析 ====================

  parse(typeNode: TypeNode): TypeStructure {
    const typeRef = typeNode as TypeReferenceNode;
    const enumName = typeRef.getTypeName().getText();

    // 查找枚举定义
    const typeDependency = CustomTypeAnalyzer.getInstance()
      .findDefinition(enumName, typeRef.getSourceFile());

    if (!typeDependency || typeDependency.typeKind !== TypeKind.ENUM) {
      throw new CustomError(`Not an enum type: ${enumName}`, ErrorCodes.IS_NOT_ENUM);
    }

    const enumDetails = typeDependency.details as EnumDetails;

    return {
      kind: PropertyKind.ENUM,
      depth: 0,
      sourceText: enumName,
      args: [],
      enumDetails: enumDetails,
      dependencies: [typeDependency]
    };
  }

  // ==================== 阶段3: 序列化器配置 ====================

  getSerializerMetadata(structure: TypeStructure, withParam?: string): SerializerMetadata {
    if (!structure.enumDetails) {
      throw new CustomError('EnumHandler: missing enumDetails in structure', ErrorCodes.ENUM_STRUCTURE_NOT_FOUND);
    }

    const enumName = structure.sourceText;
    const valueType = structure.enumDetails.valueType;
    const defaultInstantiation = this.generateInstantiation(structure);

    return {
      name: 'EnumSerializer',
      typeDeclaration: this.generateTypeDeclaration(structure),
      instantiationTemplate: this.applyWithParam(withParam, defaultInstantiation, structure),
      encodeMethod: 'encodeSerializableElement',
      decodeMethod: 'deserialize',
      decoderType: `${enumName} | undefined`,
      needsTypeAssertion: valueType === 'string'
    };
  }

  // ==================== 阶段4: 代码生成 ====================

  generateInstantiation(structure: TypeStructure): string {
    if (!structure.enumDetails) {
      throw new CustomError('EnumHandler: missing enumDetails for instantiation', ErrorCodes.ENUM_STRUCTURE_NOT_FOUND);
    }

    const enumType = structure.enumDetails.valueType;
    const enumName = `'${structure.sourceText}'`;
    const enumMembers = structure.enumDetails.members.map(member =>
      `['${member.name}', ${member.literalValue}]`
    ).join(', ');

    return `new EnumSerializer<${enumType}>(${enumName}, [${enumMembers}])`;
  }

  generateTypeDeclaration(structure: TypeStructure): string {
    if (!structure.enumDetails) {
      throw new CustomError('EnumHandler: missing enumDetails for type declaration', ErrorCodes.ENUM_STRUCTURE_NOT_FOUND);
    }

    const valueType = structure.enumDetails.valueType;
    return `EnumSerializer<${valueType}>`;
  }

  generateTypeKey(structure: TypeStructure): string {
    // 枚举类型的typeKey就是枚举名称本身
    return structure.sourceText;
  }

  // ==================== Sendable转换 ====================

  generateSendableTypeDeclaration(structure: TypeStructure): string {
    // 枚举类型本身就是Sendable兼容的，直接返回枚举名称
    return structure.sourceText;
  }

  generatePropertyConversion(_structure: TypeStructure, sourceValue: string): string {
    // 枚举值在两个方向都直接传递，不需要转换
    return sourceValue;
  }
}

/**
 * 工厂函数：创建枚举Handler
 * @returns EnumHandler实例
 */
export function createEnumHandler(): ITypeHandler {
  return new EnumHandler();
}
